// the lock server implementation

#include "lock_server.h"
#include <sstream>
#include <stdio.h>
#include <unistd.h>
#include <arpa/inet.h>

using namespace std;

lock_server::lock_server():
  nacquire (0)
{
  pthread_mutex_init(&mutex, NULL);
  pthread_cond_init(&cond_mutex, NULL);
}

lock_protocol::status
lock_server::stat(int clt, lock_protocol::lockid_t lid, int &r){
  lock_protocol::status ret = lock_protocol::OK;
  printf("stat request from clt %d\n", clt);
  r = nacquire;
  return ret;
}

lock_protocol::status 
lock_server::acquire(int clt, lock_protocol::lockid_t lid, int &r){
  // acquire 
  pthread_mutex_lock(&mutex);
  printf("Hello, Server::acquire\n");
  while (1){
    map<lock_protocol::lockid_t, char>::iterator it;
    it = locks_map.find(lid);
    if (it == locks_map.end()){
      //create new lock
      locks_map[lid] = ACQUIRED;
      pthread_mutex_unlock(&mutex);
      return lock_protocol::OK;
    } else {
      if (it->second == ACQUIRED){
	pthread_cond_wait(&cond_mutex, &mutex);
      } else {
	it->second= ACQUIRED;
	pthread_mutex_unlock(&mutex);
	return lock_protocol::OK;
      }
    }
  }
  
  return lock_protocol::OK;
}

lock_protocol::status
lock_server::release(int clt, lock_protocol::lockid_t lid, int &r){
  
  
  printf("Hello, Server::release\n");
  pthread_mutex_lock(&mutex);
  map<lock_protocol::lockid_t, char>::iterator it;
  it = locks_map.find(lid);
  it->second = RELEASED;
  pthread_cond_broadcast(&cond_mutex);
  pthread_mutex_unlock(&mutex);
  
  return lock_protocol::OK;
}
